`timescale 1ns / 1ps
//****************************************VSCODE PLUG-IN**********************************//
//----------------------------------------------------------------------------------------
// IDE :                   VSCODE     
// VSCODE plug-in version: Verilog-Hdl-Format-3.8.20250805
// VSCODE plug-in author : Jiang Percy
//----------------------------------------------------------------------------------------
//****************************************Copyright (c)***********************************//
// Copyright(C)            Please Write Company name
// All rights reserved     
// File name:              
// Last modified Date:     2025/11/18 20:04:07
// Last Version:           V1.0
// Descriptions:           
//----------------------------------------------------------------------------------------
// Created by:             Please Write You Name 
// Created date:           2025/11/18 20:04:07
// mail      :             Please Write mail 
// Version:                V1.0
// TEXT NAME:              can_protocol_encoder.v
// PATH:                   ~/Downloads/FPGA-CAN-main/FPGA-CAN/USR/can_protocol_encoder.v
// Descriptions:           
//                         
//----------------------------------------------------------------------------------------
//****************************************************************************************//

module can_protocol_encoder(
    input                       clk,
    input                       rst_n,

    input                       data_valid_in,
    input [7:0]                 data0_in,
    input [7:0]                 data1_in,
    input [7:0]                 data2_in,
    input [7:0]                 data3_in,
    input [7:0]                 data4_in,
    input [7:0]                 data5_in,
    input [7:0]                 data6_in,
    input [7:0]                 data7_in,

    output                      enc_left_a_a,
    output                      enc_left_a_b,
    output                      enc_left_b_a,
    output                      enc_left_b_b,
    output                      enc_right_a_a,
    output                      enc_right_a_b,
    output                      enc_right_b_a,
    output                      enc_right_b_b                   
);


localparam SPD_CTL = 3'd0;
localparam ACC_CTL = 3'd1;
localparam SPD_END = 3'd2;
localparam IDLE    = 3'd7;



//对于输入data_valid_in打3延时，方便后续数据处理
reg data_valid_d1;
reg data_valid_d2;
reg data_valid_d3;
always @(posedge clk or negedge rst_n)           
begin                                        
    if(!rst_n)  begin
        data_valid_d1 <= 1'b0;
        data_valid_d2 <= 1'b0;
        data_valid_d3 <= 1'b0;
    end                                                                
    else begin
        data_valid_d1 <= data_valid_in;
        data_valid_d2 <= data_valid_d1;
        data_valid_d3 <= data_valid_d2;
    end
                                                                
end  

//取得data_valid_d3上升沿
wire data_valid_pos;
assign data_valid_pos = data_valid_d3 & (~data_valid_d2);        

//数据缓存寄存器
reg [63:0] data_buf;
reg        data_buf_valid;
always @(posedge clk or negedge rst_n)           
begin                                        
    if(!rst_n)    begin
      data_buf_valid <= 1'b0;
      data_buf <= 64'd0; 
    end                                         
    else if(data_valid_pos)     begin            
        data_buf <= {data0_in, data1_in, data2_in, data3_in, data4_in, data5_in, data6_in, data7_in};  
        data_buf_valid <= 1'b1;     //BUFF数据有效标志位置1
    end                            
    else begin
        data_buf <= data_buf; 
        data_buf_valid <= 1'b0;
    end
                                   
end                                          


//数据判断状态机
reg                enc_left_dir;
reg                enc_right_dir;
reg    [15:0]       enc_left_speed;
reg    [15:0]       enc_right_speed;
reg    [2:0]       state;
always @(posedge clk or negedge rst_n)           
begin                                        
    if(!rst_n)    begin
        state <= IDLE;
        enc_left_dir <= 1'b0;
        enc_right_dir <= 1'b0;
        enc_left_speed <= 15'd0;
        enc_right_speed <= 15'd0;
    end                                         
    else begin
        case(state)
            IDLE: begin
                if(data_buf_valid) begin//当BUFF数据有效时，进入命令判断
                    case(data_buf[63:56])
                        8'h01: state <= SPD_CTL;
                        8'h02: state <= ACC_CTL;
                        default: state <= IDLE;
                    endcase
                end
                else begin
                    state <= IDLE;
                end
            end
            SPD_CTL: begin//将速度BUFF数据传递到对应寄存器
                enc_left_dir <= data_buf[40];
                enc_left_speed <= data_buf[39:24];
                enc_right_dir <= data_buf[16];
                enc_right_speed <= data_buf[15:0];
                state <= IDLE;
            end
            ACC_CTL: begin
                //预留
                state <= IDLE;
            end
            default : begin
                state <= IDLE;
            end
        endcase
    end
end   





endmodule